<template>
  <!-- 搜索 -->
  <div class="search">
    <label>
      根据姓名搜索：
    </label>
    <el-select @clear="clearSearchKey" v-model="searchKey" filterable remote clearable placeholder="输入姓名搜索"
      :remote-method="remoteMethod" :loading="searchLoading" @change="searchChange">
      <el-option v-for="item in searchOptions" :key="item.value" :label="item.label" :value="item.value" />
    </el-select>
  </div>
  <!-- 添加按钮 -->
  <div class="add">
    <el-button type="primary" :icon='Plus' @click="addStu">添加项目</el-button>
  </div>
  <!-- 展示数据的表格 -->
  <div class="table">
    <el-table :data="tableData" v-loading="tableLoading" border style="width: 100%">
      <el-table-column prop="headimgurl" align="center" label="头像">
        <template v-slot="{ row }">
          <el-avatar size="large" shape="square" :src="row.headimgurl"></el-avatar>

        </template>
      </el-table-column>
      <el-table-column prop="name" align="center" label="姓名" />
      <el-table-column prop="degree" align="center" label="学历" />
      <el-table-column prop="class" align="center" label="班级" />
      <el-table-column prop="productUrl" align="center" label="项目" />
      <el-table-column prop="cTime" align="center" label="创建时间" />
      <el-table-column prop="address" align="center" label="操作">
        <template v-slot="{ row }">
          <el-button type="primary" :icon="View" circle />
          <el-button type="primary" :icon="Edit" @click="edit(row)" circle />
          <el-button type="danger" :icon="Delete" @click="del(row)" circle />
        </template>
      </el-table-column>
    </el-table>
  </div>
  <!-- 分页 -->
  <div class="pageNation">
    <el-pagination :page-size="pageSize" @current-change="pageChange" :current-page="currentPage" background
      layout="prev,pager,next" :total="total" />
  </div>
  <!-- dialog弹窗组件 -->
  <sxDialog :dialogFormData="dialogFormData" @closed="close" :visible="dialogVisible" :title="dialogTitle"
    @dialogCancel="dialogCancel" @validateSuccess="dialogFormValidateSuccess">
    <template v-slot:upload>
      <el-upload v-loading="uploadLoading" class="avatar-uploader" method="post" action="/api/students/uploadStuAvatar"
        :show-file-list="false" name="headimgurl" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload">
        <img v-if="imageUrl" :src="imageUrl" class="avatar" />
        <el-icon v-else class="avatar-uploader-icon">
          <Plus />
        </el-icon>
      </el-upload>
    </template>
  </sxDialog>
</template>
<script setup>
// 引入dialog弹窗组件
import sxDialog from '@/components/dialog/index.vue'
import { ref, reactive } from "vue"
import * as api from "@/api/stu"
import { Plus } from '@element-plus/icons-vue'
import { onMounted } from "vue"
import { ElMessage, ElMessageBox } from 'element-plus'
//引入图标
import {
  Delete,
  View,
  Edit
} from '@element-plus/icons-vue'
//搜索逻辑
//搜索的数据
let searchOptions = ref([])
//搜索关键字
let searchKey = ref("")
//搜索的加载动画
let searchLoading = ref(false)
//搜索框输入之后会触发的方法，这里负责呈现搜索的联想数据
let remoteMethod = async (currentKeyword) => {
  if (!currentKeyword) {
    // currentPage.value = 1
    return
  }
  searchLoading.value = true
  //这个三元的目的是为了保证用户在输入或者在选择的时候都能获取到搜索关键字
  // let key=searchKey.value ? searchKey.value : currentKeyword
  try {
    // 要搜索全部的数据，所以传递字符串count,默认搜索全部
    let res = await api.searchStuListApi(currentKeyword, '')
    //给联想的列表进行赋值操作
    let repeatDatas = res.data.data.map(item => ({ value: item.name }))
    // 要去重操作
    let norepeatDatas = []
    for (var i = 0; i < repeatDatas.length; i++) {
      // 声明一个开关
      let flag = true
      for (var j = 0; j < norepeatDatas.length; j++) {
        if (repeatDatas[i].value === norepeatDatas[j].value) {
          flag = false
          break;
        }
      }
      if (flag) {
        norepeatDatas.unshift(repeatDatas[i])
      }
    }
    // console.log(repeatDatas)
    // 去重之后对options进行赋值操作
    searchOptions.value = norepeatDatas
    searchLoading.value = false
  } catch (e) {
    console.log(e)

    searchLoading.value = false
  }
}
// 清空关键字之后的方法
let clearSearchKey = () => {
  // console.log(currentPage.value)
  // 初始化数据，让页码重新回到第一页
  currentPage.value = 1
}
//用户选择了输入框的值之后,负责更新表格数据
let searchChange = async (key, page = 1, count = 10) => {
  //获取用户点选的值
  //打开表格的loading动画
  tableLoading.value = true
  //清空上次获取到的选项
  searchOptions.value = []
  try {
    let res = await api.searchStuListApi(searchKey.value, count, page)
    //对表格数据的操作,将搜索的结果赋值给表格
    tableData.value = res.data.data
    tableLoading.value = false
    //  对搜索的结果进行分页
    setPageNation(res.data.total)
  } catch (e) {
    console.log(e)
    tableLoading.value = false
  }

}
//列表逻辑
//表格数据
let tableData = ref([])
// 加载动画
let tableLoading = ref(true)
//封装一个方法，专门用于获取表格数据
let getStulist = async (page, count, classes) => {
  //开启加载动画
  tableLoading.value = true
  try {
    //请求列表数据
    let res = await api.getStuListApi(page, count, classes)
    //给表格数据赋值
    tableData.value = res.data.data
    //关闭加载动画
    tableLoading.value = false
    //设置分页器的数量
    setPageNation(res.data.total)
  } catch (e) {
    //关闭加载动画
    tableLoading.value = false
    console.log(e)
  }
}
//处理分页器
//分页器的total属性
let total = ref(1)

//一页展示多少条
let pageSize = ref(10)

// 默认的页码
let currentPage = ref(1)
//页码变更的时候
let pageChange = (inputCurrentPage) => {
  // 动态变更的时候
  currentPage.value = inputCurrentPage.value
  // 判断有没有搜索关键字，如果有那么应该更新搜索的分页结果
  if (searchKey.value) {
    searchChange(null, inputCurrentPage)
  } else {
    // 不然才是拉取列表全部的数据
    getStulist(inputCurrentPage)
  }
}
//专门修改分页器内容的方法
let setPageNation = (totalCount = 10, count = 10, currentPage = 1) => {
  total.value = totalCount
  pageSize.value = count
}

// 添加Stu信息
// 声明dialogVisible控制dialog
// dialog标题
let dialogTitle = ref('增加数据')
let dialogVisible = ref(false)

let addStu = () => {
  // 打开dialog
  dialogVisible.value = true
  dialogTitle.value = '增加数据'
}

// dialog的数据源
let dialogFormData = reactive({
  class: {
    label: '班级',
    value: ''
  },
  name: {
    label: '姓名',
    value: ''
  },
  age: {
    label: '年龄',
    value: ''
  },
  city: {
    label: '城市',
    value: ''
  },
  degree: {
    label: '学历',
    value: ''
  },
  productUrl: {
    label: '项目地址',
    value: ''
  },
  description: {
    label: '描述',
    value: ''
  }

})

// dialog点击了确定按钮，并且表单校验通过触发的逻辑
let dialogFormValidateSuccess = async (form) => {
  // 发起请求，将输入的数内容传递给服务器
  let message = '添加成功'
  let params = {
    headimgurl: '',
    class: dialogFormData.class.value,
    name: dialogFormData.name.value,
    age: dialogFormData.age.value,
    city: dialogFormData.city.value,
    degree: dialogFormData.degree.value,
    productUrl: dialogFormData.productUrl.value,
    description: dialogFormData.description.value,
  }
  // console.log(valid)
  try {

    let apiMethod = null;

    switch (dialogTitle.value) {
      case '增加数据':
        apiMethod = api.addStuApi
        // 删除sId这条属性
        params.sId ? delete params.sId : ''
        break;
      case '编辑数据':
        apiMethod = api.updateStuApi;
        // 给params中添加sId属性
        params.sId = sId.value
        // 更改提示信息
        message = '修改成功'
    }
    // 判断是否上传头像，如果上传了，那么携带到params中去
    params.headimgurl = headimgurl.value ? headimgurl.value : ''
    let res = await apiMethod(params);
    console.log(res)
    // 根据dialogTitle来区分要发送编辑请求还是发送增加请求
    // 添加成功
    // 1.提示添加成功
    ElMessage({
      type: 'success',
      message
    })
    // 2.关掉dialog
    dialogVisible.value = false
    // 3.清空表单
    form.value.resetFields()
    // 4.更新列表
    console.log(res)
    getStulist()
  } catch (e) {
    ElMessage({
      type: 'error',
      message: e.toString()
    })
    console.log(e)
  }
}

// 点击dialog取消按钮触发的逻辑
let dialogCancel = () => {
  console.log('已经取消')
  dialogVisible.value = false
}

// dialog关闭之后，要同步控制关闭属性的值
// 这么做的目的是为了处理点击空白区域或者右上角叉叉的时候，造成的后续dialog不能弹出的情况 
let close = () => {
  dialogVisible.value = false
  // 将数据清空
  let keys = Object.keys(dialogFormData)
  keys.forEach(key => {
    dialogFormData[key].value = ''
  })
  // 清空头像的回显
  imageUrl.value = ''


}

// 编辑
// 声明一个变量，存储sId,便于编辑的时候传递给后端
let sId = ref('')
let edit = (row) => {
  // 1.打开dialog
  dialogVisible.value = true;
  // 2.修改标题
  dialogTitle.value = '编辑数据'
  // 3.数据需要回显
  let keys = Object.keys(dialogFormData)
  keys.forEach(key => {
    dialogFormData[key].value = row[key]
  })
  // 给sId赋值
  sId.value = row.sId
  // 更改全局的headimgurl这个字段，便于数据的传递
  headimgurl.value = row.headimgurl
  // 回显
  imageUrl.value = row.headimgurl
}

// 上传文件
// 一个保存上传地址的变量
let imageUrl = ref()
// 声明hi歌headimgurl变量，用于将参数在表单dialog通过的时候，一并提交给后台
let headimgurl = ref('')
// 加载动画
let uploadLoading = ref(false)
// 上传成功的方法
let handleAvatarSuccess = (res, uploadFile) => {
  if (res.state) {
    // 头像上传成功
    ElMessage({
      type: 'success',
      message: res.msg
    })
    headimgurl.value = res.headimgurl
  } else {
    ElMessage({
      type: 'error',
      message: res.msg
    })
  }
  // 关闭:loading动画
  uploadLoading.value = false
  imageUrl.value = URL.createObjectURL(uploadFile.raw)
}
// 上传之前

let beforeAvatarUpload = (rawFile) => {

  // 允许上传的文件类型
  let acceptType = ['image/jpeg', 'image/png']
  // 判断当前上传的文件类型是否包含在上面的数组中
  let isAccept = acceptType.includes(rawFile.type)
  if (!isAccept) {
    ElMessage.error('上传的文件类型只能是jpeg或者是png,您当前上传的文件类型是')
    return false
  } else if (rawFile.size / 1024 / 1024 > 1) {
    ElMessage.error('上传的文件不能超过1M')
    return false
  }

  // 打开加载动画
  uploadLoading.value = true
  return true
}

// 删除
let del = (row) => {
  // 获取当前这条数据的id，传递给后台就可以了
  // 1.交互 让用户确认是否删除
  ElMessageBox.confirm('此操作将永久删除 ' + row.name + ' ，是否继续?', '删除提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  })
    .then(async () => {
      // 2.发请求，删除数据
      try {
        let res = await api.delStuApi(row.sId)
        ElMessage({
          type: 'success',
          message: '删除成功'
        })
        // 更新列表
        getStulist()
      } catch (e) {
        ElMessage({
          type: 'error',
          message: e.toString()
        })
      }
    })
    .catch(() => {
      ElMessage({
        type: 'warning',
        message: '已取消删除'
      })
    })


}

onMounted(() => {
  getStulist()
})
</script>
<script>
export default {
  meta: {
    title: 'xyxmgl',
    name: '学员项目管理',
    routeName: "stuProduct",
    icon: "icon-shangpinguanli"
  }
}
</script>
<style scoped>
.avatar-uploader .avatar {
  width: 178px;
  height: 178px;
  display: block;
}
</style>